package Pages;

import java.util.*;
import java.lang.Math;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

import clientMain.*;

/** 
 * Update User Page
 * @author Andrew Fox
 *
 */

public class UpdateUserPage extends Page{

	boolean updateEmail=false;
	boolean updatePassword=false;
	HashMap<String, StringBuffer>data=new HashMap<String,StringBuffer>();

	public UpdateUserPage(Page page){
		//		super(page.url,page.lastURL,page.client);
		//		this.html=page.html;
		//		this.pageType=page.pageType;
		super(page.url,page.html,page.client,page.pageType);
		this.pageOpenTime=page.pageOpenTime;
		this.lastURL=page.lastURL;
	}

	/**
	 * Determines the next link to go to in the application
	 * @return the URL or HTML of the next link, depending on whether
	 * 		   the previous entry contained a form or not
	 */
	public StringBuffer makeDecision() throws Exception{
		StringBuffer nextPage=new StringBuffer();
		if(HTML4)
			data=getFormData();
		ArrayList<String>changes=confirmDetails();
		StringBuffer formAction=new StringBuffer();
		if(HTML4==true){
			if(verbose)System.out.println(data);
			int start=html.indexOf("<form name=\"register_user\" action=\"")+"<form name=\"register_user\" action=\"".length();
			int end=html.indexOf("\" method=\"POST\">",start);
			formAction=new StringBuffer(html.subSequence(start,end));


			if (updatePassword==true){
				long numCharNewPassword=8+5*Math.round(Math.random());
				StringBuffer newPassword=new StringBuffer();
				for (int i=0;i<numCharNewPassword;i++){
					newPassword=newPassword.append(((char)((int)Math.random()*93+33)));
				}
				if (verbose)System.out.println(newPassword);
				client.userInfo.password=newPassword;
				data.put("password1", newPassword);
				data.put("password2", newPassword);
				changes.add("password1");
				changes.add("password2");
			}
		}
		else{
			ObjectMapper mapper = new ObjectMapper();
			if(verbose)System.out.println(html);
			JsonNode node = mapper.readValue(html.toString(), JsonNode.class);
			boolean success=node.get("updateduser").getBooleanValue();
			if (success==false){
				data.put("userID",client.userInfo.userID);
				data.put("username",client.userInfo.username);
				data.put("password",client.userInfo.password);
				data.put("email",client.userInfo.email);
				data.put("firstName",client.userInfo.firstName);
				data.put("lastName",client.userInfo.lastName);
				for (String m:data.keySet())
					changes.add(m);
			}
			else{
				nextPage=runSettings.rootURL.append("/myaccount");
			}
		}
		// Think Time
		try{Thread.sleep(getThinkTime(changes));}
		catch(InterruptedException e){
			e.printStackTrace();
		}
		if(HTML4){
			StringBuffer formname=new StringBuffer("/").append(formAction.subSequence(0,formAction.indexOf("?")));
			data.put("userID",new StringBuffer(formAction.subSequence(formAction.indexOf("=")+1,formAction.indexOf("&"))));
			data.put("authToken",new StringBuffer(formAction.subSequence(formAction.lastIndexOf("=")+1,formAction.length()-1)));
			nextPage=doSubmit3(runSettings.rootURL.append(formname),data,client);
		}
		else
			nextPage=runSettings.rootURL.append("/updateuserdetails?").append(createURL(data));
		//	client.exit=true;
		return nextPage;

	}

	/**
	 * Confirms that the details given in the form match the actual data
	 * If any data in the form is incorrect it is added to an array list
	 * @return Returns all fields which need to be changed
	 */
	public ArrayList<String> confirmDetails(){
		ArrayList<String>changes=new ArrayList<String>();
		if (data.get("password1").equals(client.userInfo.password)==false){
			changes.add(("password1"));
			data.put("password1",client.userInfo.password);}
		if (data.get("password2").equals(client.userInfo.password)==false){
			changes.add(("password2"));
			data.put("password2",client.userInfo.password);}
		if (data.get("email1").equals(client.userInfo.email)==false){
			changes.add("email1");
			data.put(("email1"),client.userInfo.email);}
		if (data.get("email2").equals(client.userInfo.email)==false){
			changes.add(("email2"));
			data.put(("email2"),client.userInfo.email);}
		if (data.get("firstname").equals(client.userInfo.firstName)==false){
			changes.add(("firstname"));
			data.put(("firstname"),client.userInfo.firstName);}
		if (data.get("lastname").equals(client.userInfo.lastName)==false){
			changes.add(("lastname"));
			data.put(("lastname"),client.userInfo.lastName);}
		if (data.get("street").equals(client.userInfo.address)==false){
			changes.add(("street"));
			data.put(("street"),client.userInfo.address);}
		if (data.get("town").equals(client.userInfo.city)==false){
			changes.add(("town"));
			data.put(("town"),client.userInfo.city);}
		if (data.get("zip").equals(client.userInfo.zipcode)==false){
			changes.add(("zip"));
			data.put(("zip"),client.userInfo.zipcode);}
		if (data.get("state").equals(client.userInfo.USStateCode)==false){
			changes.add(("state"));
			data.put(("state"),client.userInfo.USStateCode);}

		return changes;
	}

	/**
	 * Determines the think time before going to the next page
	 * Deducts from the think time the amount of time since the 
	 * page opened until this calculation is performed
	 * @return Think time in ms
	 */
	public int getThinkTime(ArrayList<String>changes){
		int thinkTime=(int)expDist(initialThinkTime);

		for (int i=0;i<changes.size();i++){
			thinkTime+=(int)(data.get(changes.get(i)).length()/client.typingSpeed);
		}
		if (verbose)System.out.println("User: "+client.userInfo.username+" - Think Time: "+thinkTime+" ms");
		return (int) ((thinkTime-(new Date().getTime()-pageOpenTime))/runSettings.thinkTimeSpeedUpFactor);
	}

}
